import { Module, Logger } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { APP_PIPE } from '@nestjs/core';
import { ConfigService, ConfigModule } from '@nestjs/config';

import { config, IGraphqlConfig } from '@/config';

import { AppController } from './app.controller';
import { AppService } from './app.service';

import { WinstonLogsModule } from '../winston-logs/winston-logs.module';
import { CacheModule } from '../cache/cache.module';
import { GraphQLValidationPipe } from '@/pipes/graphql-validation.pipe';
import { AppResolver } from '@/resolvers/app.resolver';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      // 环境变量文件
      envFilePath: [],
      load: [config],
    }),
    GraphQLModule.forRootAsync({
      async useFactory(configService: ConfigService) {
        const graphqlConfig = configService.get<IGraphqlConfig>('graphql');

        return {
          installSubscriptionHandlers: true,
          buildSchemaOptions: {
            numberScalarMode: 'integer',
          },
          sortSchema: graphqlConfig?.sortSchema,
          autoSchemaFile: graphqlConfig?.schemaDestination,
          debug: graphqlConfig?.debug,
          playground: graphqlConfig?.playgroundEnabled,
          context: ({ req }) => ({ req }),
          formatError(error) {
            const { message, extensions, path } = error;

            if (extensions?.['exception']?.['status'] === 500) {
              return {
                message: extensions?.['exception']?.['message'] || message,
                path: path,
                extensions: {
                  code: extensions?.['code'],
                  status: extensions?.['exception']?.['status'],
                  biz: {
                    code: extensions?.['exception']?.['response']?.['code'],
                    message: extensions?.['exception']?.['response']?.['msg'],
                  },
                },
              };
            } else {
              const response = extensions?.['response'] as any;

              return {
                message: response?.['message'] || message,
                path: path,
                extensions: {
                  code: extensions?.['code'],
                  status: response?.['statusCode'],
                },
              };
            }
          },
        };
      },
      inject: [ConfigService],
    }),
    WinstonLogsModule,
    CacheModule,
  ],
  controllers: [AppController],
  providers: [
    {
      provide: APP_PIPE,
      useClass: GraphQLValidationPipe,
    },
    AppService,
    Logger,
    AppResolver,
  ],
})
export class AppModule {}
